<template>
  <div class="validate-input-container pb-3">
    <input v-if="tag === 'input'" class="form-control" :class="{ 'is-invalid': inputRef.error }" :value="inputRef.value"
      @blur="validateInput" @input="updateValue" v-bind="$attrs" />
    <textarea v-else-if="tag === 'textarea'" rows="10" class="form-control" :class="{ 'is-invalid': inputRef.error }"
      :value="inputRef.value" @blur="validateInput" @input="updateValue" v-bind="$attrs" />
    <span v-if="inputRef.error" class="invalid-feedback">{{
        inputRef.message
    }}</span>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, PropType, onMounted, watch } from "vue";
import { emitter } from "@/util/util";

const emailReg =
  /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;

interface RuleProp {
  type: "required" | "email" | 'custom';
  message: string;
  validator?: () => boolean
}

export type RulesProp = RuleProp[];
export type TagType = 'input' | 'textarea'
export default defineComponent({
  //禁用 Attribute 继承
  inheritAttrs: false,
  props: {
    rules: Array as PropType<RulesProp>,
    modelValue: String,
    tag: {
      type: String as PropType<TagType>,
      default: 'input'
    }
  },

  setup(props, context) {
    watch(
      () => props.modelValue,
      (val) => {
        inputRef.value = val as string;
      }
    );
    // input 对象
    const inputRef = reactive({
      value: props.modelValue || "",
      error: false,
      message: "",
    });
    const validateInput = () => {
      if (props.rules) {
        // 检验是否通过，返回布尔值
        const allPassed = props.rules.every((rule) => {
          let passed = true;
          inputRef.message = rule.message;
          switch (rule.type) {
            case "required":
              passed = inputRef.value.trim() !== "";
              break;
            case "email":
              passed = emailReg.test(inputRef.value);
              break;
            case 'custom':
              passed = rule.validator ? rule.validator() : true
              break
            default:
              break;
          }
          return passed;
        });
        inputRef.error = !allPassed;
        return allPassed;
      }
      return true;
    };

    // 事件类型为KeyboardEvent（键盘事件）
    const updateValue = (e: Event) => {
      const targetValue = (e.target as HTMLInputElement).value;
      inputRef.value = targetValue;
      context.emit("update:modelValue", targetValue); //加update在父组件直接使用v-model，不加update，父组件需要使用监听函数
      //   context.emit("modelValue", targetValue);
    };

    onMounted(() => {
      emitter.emit("form-item-created", validateInput);
    });
    return {
      inputRef,
      validateInput,
      updateValue,
    };
  },
});
</script>

<style scoped>
</style>
